<template>
    <div class="chart-container" ref="chartRef"></div>
</template>
<style>
.chart-container {
    width: 400px;
    height: 300px;
}
</style>
<script lang="ts" setup>
import { defineProps, PropType, onMounted, ref, watch, defineEmits } from "vue"
import * as echarts from 'echarts'
import * as everpolate from "everpolate"


const props = defineProps({
    curve: {
        type: Array as PropType<number[]>,
        required: true
    }
})

const emits = defineEmits(['update:curve'])

const chartRef = ref<HTMLElement | null>(null)
const chartInstance = ref<echarts.ECharts | null>(null)
const data = ref<number[]>([])
const controlPoints = ref<number[]>(Array.from({ length: 9 }, (_, i) => (i * 16)))
const originalData = ref<number[]>([])
// 初始化 ECharts 实例
onMounted(() => {
    if (chartRef.value) {
        originalData.value = (props.curve != null && props.curve.length == 128) ? props.curve : (Array.from({ length: 129 }, (_, i) => i))
        data.value = originalData.value

        console.log('ctrlpnts', controlPoints)

        chartInstance.value = echarts.init(chartRef.value)
        updateChart()
    }
})


const symbolSize = 15;

const interpolatedPoints = (seriesData: { value: number[] }[]) => {
    const xCoords = seriesData.map((elem) => elem.value[0])
    const yCoords = seriesData.map((elem) => elem.value[1])
    const interpolationXPoints = Array.from({ length: 128 + 1 }, (_, i) => i)
    const interpolatedData = everpolate.linear(interpolationXPoints, xCoords, yCoords)
    const newCurve = interpolatedData.map(Math.round)

    newCurve.pop() // 将右侧端点弹出去
    data.value = newCurve

    emits("update:curve", newCurve)
    return data.value.map((value, i) => [i, value])
}

// 更新图表数据
const updateChart = () => {
    const seriesData = data.value.filter((value, index) => controlPoints.value.includes(index)).map((value, index) => ({
        value: [index * 16, value],
        symbolSize
    }))
    seriesData.push({
        value: [128, 128],
        symbolSize
    })

    const option = {
        xAxis: {
            type: 'value',
            min: 0,
            max: 128
        },
        yAxis: {
            type: 'value',
            min: 0,
            max: 128
        },
        series: [{
            id: 'interpolated',
            data: interpolatedPoints(seriesData),
            type: "line",
        }, {
            id: "curve",
            data: seriesData,
            type: 'line',
            smooth: false,
            symbolSize: symbolSize,
        }],

    }

    chartInstance.value?.setOption(option)
    chartInstance.value?.setOption({
        graphic: echarts.util.map(seriesData, function (dataItem, dataIndex) {
            const isDraggable = (dataIndex: number): boolean => {
                if (dataIndex === 0 || dataIndex === controlPoints.value.length - 1) {
                    return false
                } else {
                    return true
                }
            }

            return {
                // 'circle' 表示这个 graphic element 的类型是圆点。
                type: 'circle',

                shape: {
                    // 圆点的半径。
                    r: symbolSize / 2
                },
                // 用 transform 的方式对圆点进行定位。position: [x, y] 表示将圆点平移到 [x, y] 位置。
                // 这里使用了 convertToPixel 这个 API 来得到每个圆点的位置，下面介绍。
                position: chartInstance.value?.convertToPixel('grid', dataItem.value),

                // 这个属性让圆点不可见（但是不影响他响应鼠标事件）。
                invisible: true,
                // 这个属性让圆点可以被拖拽。
                draggable: isDraggable(dataIndex) ? 'vertical' : false,
                // 把 z 值设得比较大，表示这个圆点在最上方，能覆盖住已有的折线图的圆点。
                z: 100,
                // 此圆点的拖拽的响应事件，在拖拽过程中会不断被触发。下面介绍详情。
                // 这里使用了 echarts.util.curry 这个帮助方法，意思是生成一个与 onPointDragging
                // 功能一样的新的函数，只不过第一个参数永远为此时传入的 dataIndex 的值。
                ondrag: echarts.util.curry(onPointDragging, dataIndex)
            };
        })
    })
    // 拖拽某个圆点的过程中会不断调用此函数。
    // 此函数中会根据拖拽后的新位置，改变 data 中的值，并用新的 data 值，重绘折线图，从而使折线图同步于被拖拽的隐藏圆点。
    function onPointDragging(dataIndex: number) {
        // 这里的 data 就是本文最初的代码块中声明的 data，在这里会被更新。
        // 这里的 this 就是被拖拽的圆点。this.position 就是圆点当前的位置。
        seriesData[dataIndex].value = chartInstance.value?.convertFromPixel('grid', this.position);
        // seriesData[dataIndex].value[]

        // 用更新后的 data，重绘折线图。
        chartInstance.value?.setOption({
            series: [
                {
                    id: 'curve',
                    data: seriesData,
                    type: "line",
                },
                {
                    id: "interpolated",
                    data: interpolatedPoints(seriesData),
                    type: "line",
                    symbol: "circle"
                }
            ]
        });
    }
}

</script>